<template>
  <div class="link-box">
    <div class="link-box_search" v-if="searchable && hasLogin">
      <a-input
        :allowClear="true"
        :maxLength="32"
        placeholder="检索..."
        v-model="keywords"
        v-focus
      />
    </div>

    <a-row class="link-box_href" :gutter="2" type="flex" justify="start">
      <draggable
        style="width: 100%"
        v-model="curLinks"
        group="people"
        :draggable="draggable ? '.dragItem' : ''"
      >
        <a-col
          class="dragItem"
          v-for="(item, index) in curLinks"
          :key="item.value"
          :xs="12"
          :sm="8"
          :md="6"
          :lg="4"
          :xxl="3"
        >
          <a-popover placement="bottom" :title="item.name">
            <template #content>{{ item.value }}</template>
            <a
              target="_blank"
              rel="noopener noreferrer"
              :href="item.value"
              :class="['btn btn-link text-ellipsis', { active: item.active }]"
            >
              <a-avatar
                shape="square"
                :size="18"
                :src="iconApi + item.value"
              ></a-avatar>
              {{ item.name }}
              <span class="operation-box flex-box" v-if="editable">
                <my-icon
                  type="edit"
                  @click.prevent="handlerEdit(index)"
                ></my-icon>
                <a-divider type="vertical" />
                <my-icon
                  type="ashbin"
                  @click.prevent="handlerDel(index)"
                ></my-icon>
              </span>
            </a>
          </a-popover>
        </a-col>
        <a-col
          :xs="12"
          :sm="8"
          :md="6"
          :lg="4"
          :xxl="3"
          v-if="editable"
          slot="footer"
        >
          <a
            class="btn btn-link btn-add"
            href="javascript: void(0)"
            @click="handlerAdd"
          >
            <my-icon type="add-bold"></my-icon>
            添加链接</a
          >
        </a-col>
      </draggable>
    </a-row>

    <a-modal
      okText="保存"
      cancelText="取消"
      title="添加链接"
      :visible="visible"
      :confirm-loading="confirmLoading"
      @ok="handleValidate"
      @cancel="handlerCancel"
    >
      <div class="form-box">
        <a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 15 }">
          <a-form-item label="网站名称" help="请输入网站名称">
            <a-input v-model="formData.name" v-focus />
          </a-form-item>
          <a-form-item
            label="链接地址"
            help="请输入链接地址，协议以输入内容为准，点击搜索可根据URL查找网站名称"
          >
            <a-input-search
              v-model="formData.value"
              enter-button
              :loading="loading"
              @search="onSearchName"
            />
          </a-form-item>
        </a-form>
      </div>
    </a-modal>
  </div>
</template>

<script>
import { mapState } from "vuex";
import draggable from "vuedraggable";

import config from "../../json/init.json";

export default {
  components: {
    draggable,
  },
  props: ["links", "editable", "searchable", "draggable"],
  data() {
    return {
      keywords: "",
      searchLinks: [],
      visible: false,
      confirmLoading: false,
      loading: false,
      iconApi: config.iconApi,
      formData: {
        name: "",
        value: "",
      },
    };
  },
  watch: {
    keywords(val) {
      this.$funcs.debounce(() => {
        this.handlerSearch(val);
      }, 200);
    },
  },
  computed: {
    ...mapState(["hasLogin", "userInfo"]),
    curLinks: {
      get() {
        return this.searchLinks.length ? this.searchLinks : this.links;
      },
      set(val) {
        // 非检索状态下可以拖拽修改顺序
        if (!this.keywords) {
          this.handleSave(val);
        }
      },
    },
  },
  methods: {
    // 检索网站名称
    handlerSearch(text) {
      if (text.trim() !== "") {
        let links = this.links.slice();
        links.forEach((item) => {
          if (item.name.toLowerCase().indexOf(text.toLowerCase()) > -1) {
            item.active = true;
          }
        });
        this.searchLinks = links;
      } else {
        this.searchLinks = [];
        this.links.forEach((item) => {
          item.active = false;
        });
      }
    },
    // 根据地址检索网站title
    onSearchName() {
      if (this.formData.value) {
        this.loading = true;
        this.$http("/link/getHtmlTitle", { url: this.formData.value })
          .then((res) => {
            this.formData.name = res.data;
            this.loading = false;
          })
          .catch(() => {
            this.loading = false;
          });
      } else {
        this.$message.info("请直接输入完整的链接地址！");
      }
    },
    // 新增链接
    handlerAdd() {
      if (!this.hasLogin) {
        this.$message.warning("请先登录");
        return;
      }

      this.visible = true;
    },
    // 编辑链接
    handlerEdit(index) {
      if (!this.hasLogin) {
        this.$message.warning("请先登录");
        return;
      }

      this.formData = JSON.parse(JSON.stringify(this.links[index]));
      this.visible = true;
    },
    // 删除链接
    handlerDel(index) {
      let _this = this;
      _this.$confirm({
        title: "温馨提示",
        content: "您确定要删除吗？",
        okText: "确定",
        cancelText: "取消",
        onOk() {
          let links = _this.links.slice();
          links.splice(index, 1);
          _this.handleSave(links);
        },
        onCancel() {},
      });
    },
    // 保存前校验
    handleValidate() {
      if (!this.formData.name || !this.formData.value) {
        this.$message.warning("请输入网站名称和链接地址！");
        return;
      }

      this.confirmLoading = true;
      let links = JSON.parse(JSON.stringify(this.links));

      // 移除active属性
      links.forEach((item) => {
        item.active && delete item.active;
      });

      // 已经存在的不能添加，存在则替换
      let index = links.findIndex((item) => item.value === this.formData.value);
      if (index > -1) {
        links.splice(index, 1);
        links.push(this.formData);
      } else {
        links.push(this.formData);
      }
      this.handleSave(links);
    },
    // 保存到后台
    handleSave(links) {
      if (!this.hasLogin) {
        this.$message.warning("请先登录");
        return;
      }

      this.$http(
        "/link/saveMyLinks",
        { userId: this.userInfo.userId, links: JSON.stringify(links) },
        "post"
      ).then((res) => {
        if (res.code) {
          this.$message.success(res.msg);
          this.keywords = "";
          this.$store.commit("links", links);
          this.$storage.set(this.userInfo.userName + "_links", links);
          this.handlerCancel();
        } else {
          this.$message.error(res.msg);
        }
      });
    },
    handlerCancel() {
      this.formData = {
        name: "",
        value: "",
      };
      this.visible = false;
      this.confirmLoading = false;
      this.loading = false;
    },
  },
};
</script>

<style lang="less">
.link-box {
  width: 100%;
  margin: 32px auto 0;
  border: 1px solid rgba(230, 230, 231, 0.8);
  box-shadow: 0px 0px 20px 6px rgba(0, 0, 0, 0.1);
  border-radius: 4px;
  background-color: rgba(255, 255, 255, 0.5);

  &_search {
    padding: 10px;
    background-color: rgba(255, 255, 255, 0.5);

    .ant-input-affix-wrapper {
      width: 80%;
      max-width: 240px;

      .ant-input {
        border-radius: 32px;
      }
    }
  }

  &_href {
    padding: 10px;

    .btn-link {
      color: #337ab7;
      position: relative;
      box-shadow: none;
      display: inline-block;
      width: 100%;
      line-height: 28px;
      padding: 6px 12px;
      border-radius: 4px;
      transition: all 0.4s ease;

      .operation-box {
        position: absolute;
        top: 50%;
        transform: translate(100%, -50%);
        opacity: 0;
        right: 4px;
        background: #fff;
        padding: 0 4px;
        border-radius: 2px;
      }

      &:hover {
        .operation-box {
          opacity: 1;
          transform: translate(0, -50%);
          transition: all 0.4s ease;
          color: #666;
          box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);

          .my-icon {
            &:hover {
              color: #f44336;
            }
          }
        }
      }

      &:hover,
      &:visited,
      &:active {
        text-decoration: none;
        outline-style: none;
        color: #337ab7;
        background-color: rgba(255, 255, 255, 0.65);
        box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
      }

      &.active {
        background-color: rgba(71, 147, 213, 1);
        color: #fff;
      }

      &.btn-add {
        line-height: 30px;
        border: none;
        text-align: left;
        border-radius: 6px;
      }
    }
  }
}
</style>
